\section{Implementation}

We implement {\ourSystem} by modifying ZooKeeper's source code. In particular:
1) we reuse ZooKeeper's network and agreement modules to replicate metadata;
2) we add chain replication to forward data;
3) we modify the read protocol to provide linearizable and scalable reads;
4) we replace ZooKeeper's storage module with one that supports preferred, reserve, and metadata storage;
5) we modify ZooKeeper's logging system to
record PrepareData messages;
6) we implement recovery as described in Section~\ref{section-recovery}.

We apply several additional modifications to improve performance: first, {\ourSystem} modifies ZooKeeper's agreement
 module to incorporate batching~\cite{castro02practical,
   clement09upright}, which improves performance by
 about 10\% for the sequential write workload. Second, {\ourSystem} reuses memory buffers to reduce
 memory allocation. ZooKeeper's server is implemented in Java, and our profiling
shows that the overhead due to memory allocation and garbage collection is quite substantial, especially if the block size
is large (ZooKeeper is explicitly not designed for large data blocks). To alleviate this problem,
we reuse allocated memory buffers, which is not hard since they all have the same size. This device improves
read performance by about 10-15\% in our experiments.
